//by 2014302580118 ����
package match;

import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import read.*;
import extract.*;

import com.mysql.jdbc.Connection;
import com.mysql.jdbc.PreparedStatement;

public class match {
	//�洢(songId,doffset),frequence���ս��������
	
	//������
    static ArrayList<rawResult> ral = new ArrayList<rawResult>();
    
	public static void main(String[] args){
		//�������ݿ�
		Connection conn = getConn();
		//��ȡƬ��֮finger
		AudioRead test = new AudioRead("����Ƭ��/�໨�� ¼��ʱ����˵��.wav");
        double[][] timeDomain = FFT.divFrames(test.getSequence());
        Fingerprint fingerprint = new Fingerprint();
        for (int i = 0; i < timeDomain.length; ++i) {
            fingerprint.append(FFT.fft(timeDomain[i]));
        }
        //finger֮����
        ArrayList<ShazamHash> Orial=fingerprint.combineHash();
        
        //��f1,f2,dt��һ���finger����
        ArrayList<newHash> Oal=convert(Orial);
        
        System.out.println("����Ƭ��ɨ�����...\n����ƥ��...");
        int total=Oal.size();
        System.out.println("Ƭ��finger��Ϊ��" +total);
        //����ȡ��ָ�ƽ��еȼ����ȡ
        //��֮ǰȫ��ƥ��ʱδ�ܵõ���ȷ�����ǰ5��û�У��ȼ����ȡ��׼ȷ�ʴ�Ϊ��ߣ��������ǵ�һ��,���������ܵͣ�����Ϊ1����
        //��ȡ100��
        ArrayList<newHash> nal=new ArrayList<newHash>();
        for(int n=0;n<100;n++){
        	int t=(int)(total*n/100.0);
        	nal.add(Oal.get(t));
        }
        //�Դ���ָ�������ݿ��в��Ҳ�����Ӧ�������һ��ʼ����ľ�̬ArrayList�У����ʼ����������ArrayList��
        for(int i=0;i<100;i++){
        	get1ReSult(conn,nal.get(i));
       }
       
        System.out.println("ͳ����ϣ��Ժ���ʾ���...");
        //ͳ�Ƹ�(songId,doffset)���ֵ�Ƶ��
        //һ��ʼ����Map<Result,Integer>�޷�ʵ�֣�ֻ�ܽ�songId,doffset�ϳ�һ��String��ΪKey
        Map<String,Integer> m1=new HashMap<String,Integer>();
        for(int i=0;i<ral.size();i++){
     	   String s1=ral.get(i).songId+","+ral.get(i).doffset;
     	   if(!m1.containsKey(s1))
     		   m1.put(s1, 1);
     	   else{
     		   int val=m1.get(s1);
     		   m1.put(s1, val+1);
     	   }
        }
        ArrayList<Result> ar=new ArrayList<Result>();
        for(Map.Entry i : m1.entrySet()){
     	   String r= (String) i.getKey();
     	   int f=(int) i.getValue();
     	   String[] idAdo = r.split(",");
     	   int i1=Integer.parseInt(idAdo[0]);
     	   int i2=Integer.parseInt(idAdo[1]);
     	   ar.add(new Result(new rawResult(i1,i2),f));
       }
       
        int[] rawScore=new int[ar.size()];
        for(int i=0;i<ar.size();i++){
        	rawScore[i]=ar.get(i).frequence;
        }
        //����frequence����
        mergeSort(rawScore);
        int[] score =reverse(rawScore);
        
        ArrayList<Result> song = new ArrayList<Result>();
        //һ�׸���ܳ��ֶಿ�ֶ�ƥ�䣬ֻ�������ƥ��ֵ��
        ArrayList<Integer> songIdList = new ArrayList<Integer>();
        for(int i=0;i<100;i++){
        	for(int n=0;n<ar.size();n++){
        		int k=0;
        		if(score[i]==ar.get(n).frequence){
        			for(int i1=0;i1<songIdList.size();i1++){
        				if(ar.get(n).r.songId==songIdList.get(i1)){
        					k=9;
        				}
        			}
        			if(k!=9)	
        				song.add(ar.get(n));	
        				songIdList.add(ar.get(n).r.songId);
        		}
        	}
        }
        
        System.out.println("�����song����Ϊ"+song.size()+"\nǰ����ƥ�������£��ٷֱȣ���");
        //���ƥ����ǰ5�ĸ���
        //ֻ������100�׸��������ݿ⣬ƥ����ʱ��30s�ڣ�׼ȷ��90%����
        //������Լ���ȡ��������Ƶƥ��׼ȷ������90%���ϣ��ҷ�����Ϊ100
        for(int i=0;i<5;i++){
        	String songId=song.get(i).r.songId+"";
        	int fre=song.get(i).frequence;
        	String songName = getSong(conn,songId);
        	int seq = i+1;
        	System.out.println(seq+"."+songName+",which has a score :" +fre);
        }
	}
	//���鷴�ã���Ϊ�����Ľ��������
	public static int[] reverse(int[] a){
		int[] b=new int[a.length];
		for(int i=0;i<a.length;i++){
			b[i]=a[a.length-1-i];
		}
		return b;
	}
	
	//��ԭ�ȵ�(f1,f2,dt)��ָ��ArrayListת��Ϊ(fingerId)��ָ��ArrayList
	public static ArrayList<newHash> convert(ArrayList<ShazamHash> o){
		ArrayList<newHash> al=new ArrayList<newHash>();
        for(int i=0;i<o.size();i++){
        	ShazamHash s1 = o.get(i);
        	int dt=s1.dt;
        	int f1=s1.f1;
        	int f2=s1.f2;
        	int fingerId = (dt<<18)|(f1<<9)|f2;
        	int of=s1.offset;
        	al.add(new newHash(fingerId,of));
        }
        return al;
	}
	//����Ϊ�鲢����
	public static void mergeSort(int[] data) {  
        sort(data, 0, data.length - 1);  
    }  
  
    public static void sort(int[] data, int left, int right) {  
        if (left >= right)  
            return;  
        int center = (left + right) / 2;    
        sort(data, left, center);   
        sort(data, center + 1, right);    
        merge(data, left, center, right);  
    }  
  
    public static void merge(int[] data, int left, int center, int right) {  
        int[] tmpArr = new int[data.length];     
        int mid = center + 1;    
        int third = left;   
        int tmp = left;  
        while (left <= center && mid <= right) {  
            if (data[left] <= data[mid]) {  
                tmpArr[third++] = data[left++];  
            } else {  
                tmpArr[third++] = data[mid++];  
            }  
        }  
        while (mid <= right) {  
            tmpArr[third++] = data[mid++];  
        }  
        while (left <= center) {  
            tmpArr[third++] = data[left++];  
        }  
        while (tmp <= right) {  
            data[tmp] = tmpArr[tmp++];  
        }  
    }  
	
    //��ȡ���ݿ�ƥ���������д���
	public static void get1ReSult(Connection conn,newHash hash) {
		int finger=hash.fi;
		int offset = hash.offset;
		String fingerString = finger+"";
		
	    
	    String sql = "select songId,offset from songFinger where fingerId="+fingerString;
	    PreparedStatement pstmt;
	    try {
	        pstmt = (PreparedStatement)conn.prepareStatement(sql);
	        ResultSet rs = pstmt.executeQuery();
	        
	        int songId=0;
	        int offsetInDB=0;
	        int doffset=0;
	        
	        while (rs.next()) {
	            songId=rs.getInt("songId");
	            offsetInDB = rs.getInt("offset");
	            doffset=(offsetInDB-offset);
	            ral.add(new rawResult(songId,doffset));
	        }
	        rs=null;
	    } catch (SQLException e) {
	        e.printStackTrace();
	    }
	}
	//�������ݿ�����
	public static Connection getConn() {
	    String driver = "com.mysql.jdbc.Driver";
	    String url = "jdbc:mysql://localhost:3306/test?characterEncoding=utf8&useSSL=true&useServerPrepStmts=false&rewriteBatchedStatements=true";
	    String username = "root";
	    String password = "reproach";
	    Connection conn = null;
	    try {
	        Class.forName(driver); //classLoader,���ض�Ӧ����
	        conn = (Connection) DriverManager.getConnection(url, username, password);
	    } catch (ClassNotFoundException e) {
	        e.printStackTrace();
	    } catch (SQLException e) {
	        e.printStackTrace();
	    }
	    return conn;
	}
	//����songId�����ݿ�song���л�ö�Ӧ�ĸ�����
	public static String getSong(Connection conn,String songId) {	
	    String sql = "select songName from song where songId="+songId;
	    PreparedStatement pstmt;
	    String songName=null;
	    try {
	        pstmt = (PreparedStatement)conn.prepareStatement(sql);
	        ResultSet rs = pstmt.executeQuery();
	        while (rs.next()) {
	            songName=rs.getString("songName");
	        }
	    } catch (SQLException e) {
	        e.printStackTrace();
	    }
	    return songName;
	}
}
